<?php

/**
 * This is the model class for table "{{user}}".
 *
 * The followings are the available columns in table '{{user}}':
 * @property integer $id
 * @property string $profile_id
 * @property string $nickname
 * @property string $password_hash
 * @property integer $inviter_user_id
 * @property string $last_login_time
 * @property string $created_time
 * @property integer $receive_push
 * @property integer $point
 */
class User extends CActiveRecord
{
	CONST ROLE_USER = 0;
	
	CONST ROLE_OPERATOR = 1;

	public $created_time_from, $created_time_to, $summaryData;
	
	public $online_status,$password,$confirm_password,$inviter_profile_id;
	
	public $image1, $image2, $image3, $distance, $visit_time;
	
	/**
	 * Returns the static model of the specified AR class.
	 * @param string $className active record class name.
	 * @return User the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return '{{user}}';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('inviter_profile_id', 'checkInviterProfileID'),
			array('nickname', 'required', 'on'=>'insert'),
			array('nickname', 'length', 'max'=>10),
			array('nickname, profile_id', 'unique'),
			array('inviter_user_id, receive_push, point,role_id', 'numerical', 'integerOnly'=>true),
			array('lat, lon', 'numerical'),
			array('profile_id', 'length', 'max'=>255),
			array('password_hash', 'length', 'max'=>100),
			array('profile_id, nickname, password_hash, inviter_user_id, last_login_time, created_time, receive_push, point, age, area, purpose, sex, profile_status, blood_type, height, style, look, sex_interest, age_interest, style_interest, relationship_status, free_time, drinking, smoking, income, car,online_status,password,confirm_password,image1,image2,image3', 'safe'),
			
			array('nickname, password', 'required', 'on' => 'create_operator'),
			array('password', 'length', 'min' => 6, 'max' => 32, 'on' => 'changePassword, create_operator'),
            array('confirm_password', 'compare', 'compareAttribute' => 'password', 'on' => 'change_password, create_operator'),
        
			// The following rule is used by search().
			// Please remove those attributes that should not be searched.
			array('id, profile_id, nickname, password_hash, inviter_user_id, last_login_time, created_time, receive_push, point,created_time_from,created_time_to', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
			'images'=>array(self::HAS_MANY, 'ProfileImage', 'user_id'),
			'inviter'=>array(self::BELONGS_TO, 'User', 'inviter_user_id'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id' => 'ID',
			'profile_id' => Yii::t('app', 'Profile ID'),
			'nickname' => Yii::t('app', 'Nickname'),
			'password' => Yii::t('app', 'Password'),
			'confirm_password' => Yii::t('app', 'Confirm Password'),
			'password_hash' => Yii::t('app', 'Password Hash'),
			'inviter_user_id' => Yii::t('app', 'Invite User'),
			'last_login_time' => Yii::t('app', 'Last Login Time'),
			'created_time' => Yii::t('app', 'Register Time'),
			'receive_push' => Yii::t('app', 'Receive Push'),
			'point' => Yii::t('app', 'Point'),
			'profile_status' => Yii::t('app', 'Profile Status'),
			'online_status' => Yii::t('app', 'Online'),
			'sex' => Yii::t('app', 'Sex'),
			'age' => Yii::t('app', 'Age'),
			'area' => Yii::t('app', 'Area'),
			'height' => Yii::t('app', 'Height'),
			'style' => Yii::t('app', 'Style'),
			'look' => Yii::t('app', 'Look'),
			'sex_interest' => Yii::t('app', 'Sex Interest'),
			'age_interest' => Yii::t('app', 'Age Interest'),
			'style_interest' => Yii::t('app', 'Style Interest'),
			'relationship_status' => Yii::t('app', 'Relationship Status'),
			'free_time' => Yii::t('app', 'Free Time'),
			'drinking' => Yii::t('app', 'Drinking'),
			'smoking' => Yii::t('app', 'Smoking'),
			'income' => Yii::t('app', 'Income'),
			'car' => Yii::t('app', 'Car'),
			'purpose' => Yii::t('app', 'Purpose'),
			'blood_type' => Yii::t('app', 'Blood Type'),
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
	 */
	public function search()
	{
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.
		$this->getSummaryData();
		$c=new CDbCriteria;

		if ($this->created_time_from) {
			$from = date('Y-m-d',strtotime($this->created_time_from));
			$c->addCondition("created_time >= '$from'");
		}

		if ($this->created_time_to) {
			$to = date('Y-m-d 23:59:59',strtotime($this->created_time_to));
			$c->addCondition("created_time <= '$to'");
		}

		$c->compare('role_id', Role::ROLE_USER);
		$c->compare('profile_id', $this->profile_id, true);
		$c->compare('sex', $this->sex);
		$c->compare('age', $this->age);
		$c->compare('area', $this->area);
		$c->compare('nickname', $this->nickname, true);
		$this->_applyOnlineStatusFilter($c);
		return new CActiveDataProvider($this, array(
			'criteria'=>$c,
			'sort'=>array(
				'defaultOrder'=>'created_time DESC',
			)
		));
	}
	
	public function getSummaryData()
	{
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.

		$cmd=Yii::app()->db->createCommand();

		if ($this->created_time_from) {
			$from = date('Y-m-d',strtotime($this->created_time_from));
			$cmd->andWhere("created_time >= '$from'");
		}

		if ($this->created_time_to) {
			$to = date('Y-m-d 23:59:59',strtotime($this->created_time_to));
			$cmd->andWhere("created_time <= '$to'");
		}

		$cmd->select = 'count(id) as total, IFNULL(sum(receive_push),0) as push';
		$cmd->from(User::model()->tableName());
		return $cmd->queryRow();
	}
	
	public function getOnlineStatusListData() {
		return array(
			1 => Yii::t('app', '10 minutes'),
			2 => Yii::t('app', '15 minutes'),
			3 => Yii::t('app', '30 minutes'),
			4 => Yii::t('app', '1 hour'),
			5 => Yii::t('app', '12h hour'),
			6 => Yii::t('app', '1 day'),
			7 => Yii::t('app', '7 days'),
			8 => Yii::t('app', '> 8 days'),
		);
	}
	
	private function _applyOnlineStatusFilter(CDbCriteria $c){
		switch($this->online_status) {
			case 1:	// 10 minutes
				$c->addCondition("TIMESTAMPDIFF(MINUTE,last_login_time, NOW()) <= 10");
				break;
				
			case 2:	// 15 minutes
				$c->addCondition("TIMESTAMPDIFF(MINUTE,last_login_time, NOW()) <= 15");
				break;
				
			case 3:	// 30 minutes
				$c->addCondition("TIMESTAMPDIFF(MINUTE,last_login_time, NOW()) <= 30");
				break;
				
			case 4:	// 1 hour
				$c->addCondition("TIMESTAMPDIFF(HOUR,last_login_time, NOW()) <= 1");
				break;
				
			case 5:	// 12 hour
				$c->addCondition("TIMESTAMPDIFF(HOUR,last_login_time, NOW()) <= 12");
				break;
				
			case 6:	// 1 day
				$c->addCondition("TIMESTAMPDIFF(DAY,last_login_time, NOW()) <= 1");
				break;
				
			case 7:	// 7 day
				$c->addCondition("TIMESTAMPDIFF(DAY,last_login_time, NOW()) <= 7");
				break;
				
			case 8:	// >8 day
				$c->addCondition("TIMESTAMPDIFF(DAY,last_login_time, NOW()) >= 8");
				break;
				
		}
	}
	
	public function checkInviterProfileID($attribute, $params){
		if (empty($this->$attribute))
			return;
			
		$u = $this->findByAttributes(array("profile_id"=>$this->$attribute));
		if (!$u)
			$this->addError($attribute, Yii::t('api', 'User not exists'));
		else
			$this->inviter_user_id = $u->id;
	}
	
	public function generateProfileID() {
		$maxId = Yii::app()->db->createCommand("SELECT MAX(id) FROM {$this->tableName()}")->queryScalar()+1;
		return $maxId + 1000000;
	}
	
	public function generateOperatorProfileID() {
		$maxId = Yii::app()->db->createCommand("SELECT MAX(id) FROM {$this->tableName()}")->queryScalar()+1;
		return 'OP'.($maxId + 1000000);
	}
	
	public function saveImage() {
		$saveImg = false;
		for($i=1;$i<=3;$i++){
			$attr = "image$i";
			if (!empty($this->$attr)) {
				$saveImg = true;
				break;
			}
		}
		
		if (!$saveImg) return;
		ProfileImage::model()->deleteAll("user_id={$this->id}");
		
		for($i=1;$i<=3;$i++){
			$attr = "image$i";
			if (empty($this->$attr)) continue;
			
			$img = new ProfileImage();
			$img->user_id = $this->id;
			$img->file = $this->$attr;
			$img->save();
		}
	}
	
	public function loadImage() {
		if ($this->isNewRecord) return;
		$images = ProfileImage::model()->findAll("user_id={$this->id}");
		
		foreach($images as $i => $img){
			$attr = "image".($i+1);
			$this->$attr = $img->file;
			if ($i==2) break;
		}
	}
	
	public function getPublicInfo($includeImage=true) {
		$result = $this->attributes;
		if ($includeImage) {
			$this->loadImage();
			$result['image1'] = $this->image1;
			$result['image2'] = $this->image2;
			$result['image3'] = $this->image3;
		}
		return $result;
	}
	
	public function updatePublicInfo($data) {
		$restricted = array(
			'id',
			'role_id',
			'nickname',
			'password_hash',
			'profile_id',
			'inviter_user_id',
			'last_login_time',
			'created_time',
		);
		
		foreach($restricted as $r) {
			unset($data[$r]);
		}
		
		$this->attributes = $data;
		return $this->save();
	}
	
	public function findByLocation($lat, $lon, $radius, $sex=null) {
		$c=new CDbCriteria;
		$c->select =
			"t.*, ((ACOS(SIN($lat * PI() / 180) * SIN(lat * PI() / 180) 
			+ COS($lat * PI() / 180) * COS(lat * PI() / 180) 
			* COS(($lon - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) * 1.609344 AS `distance`";
		$c->having = "`distance` <= $radius";
		$c->compare('sex', $sex);
		$c->compare('role_id', Role::ROLE_USER);
		$c->order = '`distance` ASC';
		return $this->findAll($c);
	}
	
	public function createOpenfireAccount() {
		$server = Yii::app()->params['openfireServer'];
		$port = Yii::app()->params['openfirePort'];
		$params = array(
			'secret'=>Yii::app()->params['openfireSecretKey'],
			'username'=>$this->nickname,
			'password'=>$this->nickname,
			'name'=>$this->nickname,
			'email'=>$this->nickname."@{$server}",
		);
		$apiUrl = "http://{$server}:{$port}/plugins/userService/userservice?type=add&".http_build_query($params);
		$resp = file_get_contents($apiUrl);
		
		if (strpos($resp, '<error>')!==false) 
			return false;
		return true;
	}
	
	public function searchOperator() {
		$c=new CDbCriteria;
		$c->compare('role_id', Role::ROLE_OPERATOR);
		return new CActiveDataProvider($this, array(
			'criteria'=>$c,
			'sort'=>array(
				'defaultOrder'=>'created_time DESC',
			)
		));		
	}
	
	public function addPoint($feeName, $increase=true) {
		$c=new CDbCriteria;
		$d = date('Y-m-d');
		$c->compare('name', $feeName);
		$c->addCondition("effect_from IS NULL OR effect_from <= '$d'");
		$c->addCondition("effect_to IS NULL OR effect_to >= '$d'");
		$pointFee = PointFee::model()->find($c);
		if (!$pointFee) return;
		
		$point = $this->sex ? $pointFee->male_point : $pointFee->female_point;
		if (!$increase)
			$point = -$point;
		$this->point = ($this->point+$point)>0 ? $this->point+$point : 0;
		$this->update('point');
	}
}